/*
Copyright 2022.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.

// RenderJobSpec defines the desired state of RenderJob
type RenderJobSpec struct {
	// RenderQueueManfests is the configmap name which RenderJob can be use to parse how many shot would be render.
	RenderQueueManfests string `json:"renderQueueManfests,omitempty"`
	RenderTimeOut       int    `json:"renderTimeOut,omitempty"` //渲染超时时间，单位(分钟)
	// related to kafka topic, topic name format: <tenantNamespace.JobID>
	Topic string `json:"topic,omitempty"`
	// +kubebuilder:validation:Enum=start;stop
	Operation           string              `json:"operation"`
	RenderPlugin        RenderPlugin        `json:"renderPlugin,omitempty"`
	ResourceDependences ResourceDependences `json:"resourceDependences,omitempty"`
	Priority            string              `json:"priority,omitempty"`
	InputConfig         InputConfig         `json:"inputConfig,omitempty"`
	OutputConfig        OutputConfig        `json:"outputConfig,omitempty"`
	HostConfig          HostConfig          `json:"hostConfig,omitempty"` //渲染机器配置规格
	//+optional
	// 资源释放策略设置，None-渲染完成后立即释放；延时释放，单位小时或天，eg:1h 1d
	RetentionDuration string `json:"retentionDuration,omitempty"`
}
type OutputConfig struct {
	OutputPath string `json:"outputPath,omitempty"`
	// what time the data will keep
	Retention string `json:"retention,omitempty"`
	Fromat    string `json:"format,omitempty"`
	DPI       string `json:"dpi,omitempty"`
	FrameRate string `json:"framRate,omitempty"`
	FrameFile string `json:"frameFile,omitempty"`
	Quality   string `json:"Quality,,omitempty"`
}

type InputConfig struct {
	ProjectFilePath string `json:"projectFilePath,omitempty"`
	//+optional 提交渲染任务时UE项目工程的名称，取值：项目工程名称(不包含.uproject后缀) + 时间戳
	ProjectName string `json:"projectName,omitempty"`
	// UE binary path,optional
	UEPath string `json:"uePath,omitempty"`
	// args for a UE render cmd
	UEArgs    []string `json:"ueArgs,omitempty"`
	UEVersion string   `json:"ueVersion,omitempty"`
}

// render plugin configuration
type RenderPlugin struct {
	Name string `json:"name,omitempty"`
	// plugin configuration
	Config string `json:"config,omitempty"`
	// install scripts
	Installation string `json:"installation,omitempty"`
}

type ResourceDependences struct {
	ResourcePoolReference ResourcePoolReferce `json:"resourcePoolReference,omitempty"`
	RecyclingPolicy       string              `json:"recyclingPolicy"`
}

type ResourcePoolReferce struct {
}

type PhaseStatus string

type HostFlavorDetail struct {
	CPUType string `json:"cpuType,omitempty"`
	CPUArch string `json:"cpuArch,omitempty"`
	Vcpu    int32  `json:"vcpu,omitempty"`
	GpuType string `json:"gpuType,omitempty"`
	Vgpu    int32  `json:"vgpu,omitempty"`
	Vmemory int64  `json:"vmemory,omitempty"`
}

const (
	// Prepare cloud resource stage
	JobResourcePending PhaseStatus = "Pending"
	// Prepare cloud resource stage reeady
	JobResourceReady PhaseStatus = "Ready"
	// renderjobs alreay deliverd into Kakfa
	JobQueueing PhaseStatus = "Queueing"
	// any shot in rendejobs alreay reander alreay
	JobRendering PhaseStatus = "Rendering"
	// renderjob cancelled
	JobCancelled PhaseStatus = "Cancelled"
	// renderjob failed
	JobFailed PhaseStatus = "Failed"
	// all shot in rendejobs have done
	JobDone PhaseStatus = "Done"
)

// RenderJobStatus defines the observed state of RenderJob
type RenderJobStatus struct {
	ShotStatus    []JobShotStatus `json:"shotStatus,omitempty"` //拆分后渲染任务的状态
	AvailNodes    []Host          `json:"availNodes,omitempty"` //可调度主机信息
	ElapsedTime   metav1.Time     `json:"elapsedTime,omitempty"`
	RemainingTime metav1.Time     `json:"remainingTime,omitempty"`
	StartTime     metav1.Time     `json:"startTime,omitempty"` //总任务开始渲染时间
	EndTime       metav1.Time     `json:"endTime,omitempty"`   //全部镜头渲染完成时间
	FailedFrame   int64           `json:"failedFrame,omitempty"`
	SucessFrame   int64           `json:"sucessFrame,omitempty"`
	TotalFrame    int64           `json:"totalFrame,omitempty"`
	TotalShots    int64           `json:"totalShots,omitempty"` //拆分后渲染任务的总数
	// the status of renderjob
	Phase PhaseStatus `json:"phase,omitempty"` //渲染状态
	//+optional
	TaskDelivered  bool        `json:"taskDelivered,omitempty"`  //渲染任务是否下发完成
	CurrentPID     int         `json:"currentPID,omitempty"`     //当前任务的ID号
	CurrentPercent string      `json:"currentPercent,omitempty"` //当前进度
	Conditions     []Condition `json:"conditions,omitempty"`
}

type JobShotStatus struct {
	Name          string `json:"name,omitempty"`           // shotName
	ScheduledHost string `json:"schedulerdHost,omitempty"` // shcedulerd host information
	Phase         string `json:"phase,omitempty"`          //渲染shot状态
	Percent       int    `json:"percent,omitempty"`        //渲染进度
	//+optional
	Camera             Camera      `json:"camera,omitempty"`             //渲染任务分配的镜头
	StartTime          metav1.Time `json:"startTime,omitempty"`          //开始渲染时间
	EndTime            metav1.Time `json:"endTime,omitempty"`            //结束渲染时间
	LastUpdateTime     metav1.Time `json:"lastUpdateTime,omitempty"`     //最近一次更新时间
	LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` //最近状态变化时间
	//+optional
	TimeLine []TimeLineItem `json:"timeLine,omitempty"` //渲染过程时间点
	//+optional
	Comment string `json:"comment,omitempty"` //渲染过程备注信息
}

// TOOD:主机用户名密码加密
type Host struct {
	IP     string `json:"IP,omitempty"`     // 主机IP
	Name   string `json:"name,omitempty"`   // 主机名称
	User   string `json:"user,omitempty"`   // 登录主机用户名
	Passwd string `json:"passwd,omitempty"` // 登录主机密码
	Phase  string `json:"phase,omitempty"`  // 主机状态
	//+optional
	ObtainTime metav1.Time `json:"obtainTime,omitempty"`
}

type Camera struct {
	Sequence string `json:"sequence,omitempty"` // 关卡序列号
	Shot     string `json:"shot,omitempty"`     //摄像头号
}

type HostConfig struct {
	VPCRef           string           `json:"vpcRef,omitempty"`
	ImageRef         string           `json:"imageRef,omitempty"` // 镜像ID，渲染用64bit windows
	FlavorRef        string           `json:"flavorRef,omitempty"`
	ProviderRef      ProviderRef      `json:"providerRef,omitempty"`
	Replicas         int              `json:"replicas,omitempty"`   //主机数量
	FileVolume       FileVolumeSpec   `json:"fileVolume,omitempty"` // 文件存储
	RootVolume       *VolumeSpec      `json:"rootVolume,omitempty"` // 系统盘
	DataVolume       *VolumeSpec      `json:"dataVolume,omitempty"` // 数据盘
	ResourceAffinity ResourceAffinity `json:"resourceAffinity,omitempty"`
	//+optional store cpu、gpu、memory info
	HostFlavorDetail HostFlavorDetail `json:"hostFlavorDetail,omitempty"` //规格详情
}

type ResourceAffinity struct {
	// resourceids is map that saves related DB ids
	ResourceIDs map[string]string `json:"resourceIDs"`
	// ResourceID  string         `json:"resourceID,omitempty"` // 所属资源ID
	// HostID       string `json:"hostID,omitempty"`       //商品主机的ID
	// DiskID       string `json:"diskID,omitempty"`       //商品磁盘的ID
	// FileVolumeID string `json:"fileVolumeID,omitempty"` //商品文件存储ID
	// FlavorID    string         `json:"flavorID,omitempty"`   // 主机规格
}

// type SkusInfo struct {
// 	HostID       string `json:"hostID,omitempty"`       //商品主机的ID
// 	DiskID       string `json:"diskID,omitempty"`       //商品磁盘的ID
// 	FileVolumeID string `json:"fileVolumeID,omitempty"` //商品文件存储ID
// }

type ProviderRef struct {
	Namespace string `json:"namespace,omitempty"`
	SecretRef string `json:"secretRef,omitempty"`
}

type VolumeSpec struct {
	Size       int32  `json:"size,omitempty"`
	Count      int32  `json:"count,omitempty"`
	VolumeType string `json:"volumeType,omitempty"`
	MountPoint string `json:"mountPoint,omitempty"`
	Shareable  bool   `json:"shareable,omitempty"`
}

type FileVolumeSpec struct {
	ShareProto     int32  `json:"shareProto,omitempty"`
	ShareType      bool   `json:"shareType,omitempty"`
	Size           int32  `json:"size,omitempty"`
	FilePath       string `json:"filePath,omitempty"`
	FileVolumeName string `json:"fileVolumeName,omitempty"` //商品文件存储名称
}

type TimeLine struct {
	Items []TimeLineItem `json:"items,omitempty"`
}

type TimeLineItem struct {
	SpotTime  metav1.Time `json:"spot_time,omitempty"` // 提取的渲染时间点
	Host      string      `json:"host_name,omitempty"`
	LogDetail string      `json:"log_detail,omitempty"` //渲染关键日志
	Message   string      `json:"message,omitempty"`    //渲染结论
}

func (t TimeLine) Len() int {
	return len(t.Items)
}

func (t TimeLine) Less(i, j int) bool {
	return t.Items[i].SpotTime.Before(&t.Items[j].SpotTime)
}

func (t TimeLine) Swap(i, j int) {
	t.Items[i], t.Items[j] = t.Items[j], t.Items[i]
}

type ConditionType string
type JobStatus string

// These are valid conditions of renderjob.
const (
	// 任务状态
	JobType ConditionType = "Job"
	// 素材下载
	MeterialType ConditionType = "Material"
)

type Condition struct {
	// Type of deployment condition.
	Type ConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=ConditionType"`
	// Status of the condition, one of True, False, Unknown.
	Status JobStatus `json:"status" protobuf:"bytes,2,opt,name=status"`
	// The last time this condition was updated.
	LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty" protobuf:"bytes,6,opt,name=lastUpdateTime"`
	// Last time the condition transitioned from one status to another.
	LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,7,opt,name=lastTransitionTime"`
	// The reason for the condition's last transition.
	Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
	// A human readable message indicating details about the transition.
	Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
}

type ShotRenderStatusType string

// These are valid conditions of installation.
const (
	ShotRenderStart ShotRenderStatusType = "Start"       //可渲染
	ShotRendering   ShotRenderStatusType = "Progressing" //渲染中
	ShotRenderEnd   ShotRenderStatusType = "Finished"    //渲染完成
)

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:scope=Namespaced

// RenderJob is the Schema for the renderjobs API
type RenderJob struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   RenderJobSpec   `json:"spec,omitempty"`
	Status RenderJobStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// RenderJobList contains a list of RenderJob
type RenderJobList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []RenderJob `json:"items"`
}

func init() {
	SchemeBuilder.Register(&RenderJob{}, &RenderJobList{})
}
